ShowTable of Contents
Overview
It's often the case that developers must write secure code that interacts with secure resources such as sockets or web services. After creating code to communicate over the HTTPS protocol, developers are normally confronted with SSL errors. For example, the following error is typical.
Caused by:
javax.net.ssl.SSLHandshakeException:
java.security.cert.CertificateException: CWPST508W: Certificate chain root is not a trusted certificate authority.
This is resolved by importing the SSL certificate used by the external resource into the Java VM's keystore. Developers may be already familiar with tools such as IKEYMAN that allow administrators to install certificates into the cacerts keystore. But assuming a new certificate - not already in Expeditor clients - has been created, how can developers deploy the new certificate to existing clients?
Default Certificate Handling
If the code is using the javax.net.ssl.HttpsURLConnection class, which is wrapped by the Expeditor client, the following message may be seen.
In some scenarios, users can elect to install the certificate themselves. For other scenarios such as web services or custom HTTPS code, the certificate may need to be added to the keystore prior to code execution.
Obtaining the Certificate
Other than having the certificate on file, the easiest way to obtain a certificate is by accessing the resource in a browser and exporting the certificate. Do the following.
- In the Firefox we browser, access the resource over the web using the HTTPS URL. Firefox will prompt you to make an exception provided the certificate does not already exist in the browser.
- Click "Add security exception" and the "Get Certificate" button.
- Click the "View" button to access the certificate.
- Finally click the "Export" button on the "Details" tab.
- Save the file as an X.509 Certificate (PEM) file.
Installing the Certificate
Now that you have a certificate, the file can be added to the root folder of a plugin. Using the plugin's Activator as an entry point, the following code illustrates how one might deliver the certificate via a plugin and have the plugin complete the installation.
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
// get the certificate file from this plugin
String certFile = FileLocator.getBundleFile(context.getBundle())
.toString()
+ File.separator + "certificate.crt";
System.out.println("Installing " + certFile);
if (SecurePlatform.isEnabled() && SecurePlatform.isLoggedIn()) {
// obtain the KeyStore
KeyStore ks = SecurePlatform.getKeyStore();
int ksSize = ks.size(); // current number of certs
// create a certificate
CertificateFactory fac = CertificateFactory.getInstance("X509");
Certificate cert = fac.generateCertificate(new FileInputStream(
certFile));
ks.setCertificateEntry("entrust", cert); // add the cert
// save the new keystore
File file = new File(SecurePlatform.getKeyStoreUrl().getFile());
SecurePlatform.getKeyStore().store(new FileOutputStream(file),
SecurePlatform.getPBEKeySpec().getPassword());
// check if the certificate was added
if (SecurePlatform.getKeyStore().size() == ksSize + 1) {
System.out.println("Successfully added certificate");
} else {
System.err.println("Failed to add certificate");
}
} else {
System.err
.println("Verify that the platform is running and currently logged in");
}
}
Be mindful that the reference to the certificate is through the File handle. Deployers should add the plugin to a feature and ensure the "Unpack the plug-in archive after installation" check box on the "Plug-ins" tab is selected. If not done, the plugin will be compressed as a JAR and the certificate file unavailable. The code also assumes that it is run after the platform has been logged in (presumably by the user or via SSO). Accommodations should be made to start the plugin after this event has occurred.